﻿using System;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace QtingvisionAIService
{
    public partial class QtingvisionAIService : ServiceBase
    {
        // 声明DLL函数
        [DllImport("AdcDemo.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int processImage(
            [MarshalAs(UnmanagedType.LPStr)] string imagePath,
            [MarshalAs(UnmanagedType.LPStr)] string outputPath,
            float opacity = 0.1f,
            int saveResultImg = 0);

        [DllImport("AdcDemo.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int initialize(
            [MarshalAs(UnmanagedType.LPStr)] string modelFolder);

        // 假设 AdcDemo.dll 提供了以下方法，需根据实际情况调整
        [DllImport("AdcDemo.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int loadTags(
            [MarshalAs(UnmanagedType.LPStr)] string tagPath);

        [DllImport("AdcDemo.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int dispose();

        private CancellationTokenSource cancellationTokenSource;
        private string modelFolder;
        private readonly string pipeName = @"\\.\pipe\QtingvisionAIPipe";
        private bool isInitialized = false;

        public QtingvisionAIService()
        {
            this.ServiceName = "QtingvisionAIService";
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            cancellationTokenSource = new CancellationTokenSource();
            WriteToLog("Service starting...");
            Task.Run(() => StartNamedPipeServer(cancellationTokenSource.Token));
        }

        protected override void OnStop()
        {
            cancellationTokenSource?.Cancel();
            WriteToLog("Service stopped");
            cancellationTokenSource?.Dispose();
        }

        public async void Test(string comand)
        {
            string request = comand;
            string response = "";
            if (!string.IsNullOrEmpty(request))
            {
                string[] parts = request.Split('|');
                if (parts.Length > 0)
                {
                    string command = parts[0];
         

                    switch (command)
                    {
                        case "INIT" when parts.Length == 2:
                            response = await HandleInitialize(parts[1]);
                            break;
                        case "LOADTAGS" when parts.Length == 2:
                            response = await HandleLoadTags(parts[1]);
                            break;
                        case "PROCESS" when parts.Length == 5:
                            response = await HandleProcessImage(parts[1], parts[2], float.Parse(parts[3]), int.Parse(parts[4]));
                            break;
                        case "DISPOSE" when parts.Length == 1:
                            response = await HandleDispose();
                            break;
                        default:
                            response = "Invalid command";
                            break;
                    }
                }
            }
        }
        private async Task StartNamedPipeServer(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    using (var pipeServer = new NamedPipeServerStream("QtingvisionAIPipe", PipeDirection.InOut))
                    {
                        WriteToLog("Waiting for client connection...");
                        await pipeServer.WaitForConnectionAsync(cancellationToken);

                        using (var reader = new StreamReader(pipeServer))
                        using (var writer = new StreamWriter(pipeServer))
                        {
                            string request = await reader.ReadLineAsync();
                            WriteToLog("client connection...    " + request);

                            if (!string.IsNullOrEmpty(request))
                            {
                                string[] parts = request.Split('|');
                                if (parts.Length > 0)
                                {
                                    string command = parts[0];
                                    string response;

                                    switch (command)
                                    {
                                        case "INIT" when parts.Length == 2:
                                            response = await HandleInitialize(parts[1]);
                                            break;
                                        case "LOADTAGS" when parts.Length == 2:
                                            response = await HandleLoadTags(parts[1]);
                                            break;
                                        case "PROCESS" when parts.Length == 5:
                                            response = await HandleProcessImage(parts[1], parts[2], float.Parse(parts[3]), int.Parse(parts[4]));
                                            break;
                                        case "DISPOSE" when parts.Length == 1:
                                            response = await HandleDispose();
                                            break;
                                        default:
                                            response = "Invalid command";
                                            break;
                                    }

                                    await writer.WriteLineAsync(response);
                                    await writer.FlushAsync();
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    WriteToLog($"Pipe server error: {ex.Message}");
                }
            }
        }

        private async Task<string> HandleInitialize(string modelPath)
        {
            if (isInitialized)
            {
                return "Model already initialized";
            }

            try
            {
                modelFolder = modelPath;
                int initResult = initialize(modelFolder);
                isInitialized = initResult == 0;
                string message = initResult == 0 ? "Model initialized successfully" : $"Model initialization failed, error code: {initResult}";
                WriteToLog(message);
                return message;
            }
            catch (Exception ex)
            {
                WriteToLog($"Initialization error: {ex.Message}");
                return $"Initialization error: {ex.Message}";
            }
        }

        private async Task<string> HandleLoadTags(string tagPath)
        {
            if (!isInitialized)
            {
                return "Model not initialized";
            }

            try
            {
                int result = loadTags(tagPath);
                string message = result == 0 ? "Tags loaded successfully" : $"Tags loading failed, error code: {result}";
                WriteToLog(message);
                return message;
            }
            catch (Exception ex)
            {
                WriteToLog($"Load tags error: {ex.Message}");
                return $"Load tags error: {ex.Message}";
            }
        }

        private async Task<string> HandleProcessImage(string imagePath, string outputPath, float opacity = 0.2f, int saveResultImg = 0)
        {
            if (!isInitialized)
            {
                return "Model not initialized";
            }

            try
            {
                if (!Directory.Exists(outputPath))
                {
                    Directory.CreateDirectory(outputPath);
                }

                int result = processImage(imagePath, outputPath, opacity, saveResultImg);
                string message = result == 0 ? "Processing successful" : $"Processing failed, error code: {result}";
                WriteToLog(message);
                return message;
            }
            catch (Exception ex)
            {
                WriteToLog($"Processing error: {ex.Message}");
                return $"Error: {ex.Message}";
            }
        }

        private async Task<string> HandleDispose()
        {
            try
            {
                int result = dispose();
                isInitialized = false;
                string message = result == 0 ? "Disposed successfully" : $"Dispose failed, error code: {result}";
                WriteToLog(message);
                return message;
            }
            catch (Exception ex)
            {
                WriteToLog($"Dispose error: {ex.Message}");
                return $"Dispose error: {ex.Message}";
            }
        }

        private void WriteToLog(string message)
        {
            try
            {
                string logPath = @"C:\Logs\QtingvisionAIService.txt";
                string directory = Path.GetDirectoryName(logPath);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }
                File.AppendAllText(logPath, $"{DateTime.Now}: {message}\n");
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("QtingvisionAIService", $"Log write failed: {ex.ToString()}",
                    System.Diagnostics.EventLogEntryType.Error);
            }
        }
    }
}